package com.sljr.mvndemo;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;
import freemarker.template.Version;

public class Tool {
	public static void main(String[] args) {
		String groupName = "com.sljr";
		String projectName = "p2p";
		String baseDir = "D:\\personal\\workspace\\"+projectName+"\\src\\main\\java\\";
		String testBaseDir = "D:\\personal\\workspace\\"+projectName+"\\src\\test\\java\\";
		String resDir = "D:\\personal\\workspace\\"+projectName+"\\src\\main\\resources\\";
		String testResDir = "D:\\personal\\workspace\\"+projectName+"\\src\\test\\resources\\";
		
		Map<String, List<Map<String, Object>>> tableInfoCache = new HashMap<String, List<Map<String, Object>>>(); 
		
		String sql = "select t.table_name, tc.column_name, tc.data_type, tc.data_length from user_tables t, user_tab_columns tc where t.table_name = tc.table_name and t.table_name = 'COM_T_USER'";
		List<Map<String,Object>> list = DbUtil.execute(sql);
		
		for(Map<String, Object> map : list) {
			List<Map<String, Object>> curTable = tableInfoCache.get(map.get("TABLE_NAME"));
			if(curTable == null) {
				curTable = new ArrayList<Map<String, Object>>();
			}
			curTable.add(map);
			
			tableInfoCache.put(map.get("TABLE_NAME").toString(), curTable);
		}
		
		System.out.println();
		
		
		clear(Arrays.asList(baseDir, testBaseDir, resDir, testResDir));
		
//		generateTestBase(testBaseDir, groupName, projectName);
//		generateJdbcBase(resDir);
//		generateMybatisConfigBase(resDir);
//		generateLogConfig(resDir);
//		generateTestRes(testResDir);
//		
//		generateModel(tableInfoCache, groupName, projectName, baseDir);
//		generateVO(tableInfoCache, groupName, projectName, baseDir);
		generateMyBatisMapper(tableInfoCache, groupName, projectName, resDir);
		generateDaoMapper(tableInfoCache, groupName, projectName, baseDir);
//		generateMapperTestCase(tableInfoCache, groupName, projectName, baseDir);
		
	}
	
	public static void generateTestRes(String testResDir) {
		Map<String, Object> data = new HashMap<String, Object>();
		data.put("driver", DbUtil.getDriver());
		data.put("url", DbUtil.getUrl());
		data.put("username", DbUtil.getUsername());
		data.put("password", DbUtil.getPassword());
		generate("base\\jdbc.properties.ftl", data, "jdbc.test.properties", testResDir+"\\");
	}
	/**
	 * 生成日志配置文件，采用logback和log4j
	 * @param resDir
	 */
	private static void generateLogConfig(String resDir) {
		Map<String, Object> data = new HashMap<String, Object>();
		generate("base\\logback.xml.ftl", data, "logback.xml", resDir);
	}

	/**
	 * 生成mybatis文件
	 * @param resDir
	 */
	private static void generateMybatisConfigBase(String resDir) {
		Map<String, Object> data = new HashMap<String, Object>();
		generate("base\\mybatis-config.xml.ftl", data, "mybatis-config.xml", resDir +"\\mybatis\\");
	}
	private static void generateJdbcBase(String resDir) {
		Map<String, Object> data = new HashMap<String, Object>();
		data.put("driver", DbUtil.getDriver());
		data.put("url", DbUtil.getUrl());
		data.put("username", DbUtil.getUsername());
		data.put("password", DbUtil.getPassword());
		generate("base\\jdbc.properties.ftl", data, "jdbc.properties", resDir+"\\");
	}
	private static void clear(List<String> dirs) {
		if(null == dirs || dirs.isEmpty()) {
			return;
		}
		
		for(String dir : dirs) {
			DirUtil.clearPath(dir);
		}
	}
	private static void generateTestBase(String testBaseDir, String groupName, String projectName) {
		Map<String, Object> data = new HashMap<String, Object>();
		
		data.put("pkgName", groupName+"."+projectName);
		
		generate("base\\AbstractMapperTestCase.ftl", data, "AbstractMapperTestCase.java", testBaseDir + groupName.replace(".", "\\") +"\\"+ projectName + "\\");
		
	}
	/**
	 * 
	 * @param columnName user_email_code
	 * @return userEmailCode
	 */
	private static String convertColumnToProperty(String columnName) {
		String[] strings = columnName.split("_");
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < strings.length; i++) {
			sb.append(StringUtil.upperFirstLetter(strings[i].toLowerCase()));
		}
		return StringUtil.lowerFirstLetter(sb.toString());
	}
	
	private static String convertTableNameToClassName(String tableName) {
		String[] strings = tableName.split("_");
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < strings.length; i++) {
			sb.append(StringUtil.upperFirstLetter(strings[i].toLowerCase()));
		}
		return sb.toString();
	}
	
	public static void generate(String template, Map<String, Object> data, String result, String targetDir) {
		
		try {
			Configuration cfg = new Configuration();
			cfg.setDirectoryForTemplateLoading(new File("src\\main\\resources\\templates"));
			cfg.setObjectWrapper(new DefaultObjectWrapper());
//			cfg.setObjectWrapper(ObjectWrapper.BEANS_WRAPPER);
			cfg.setDefaultEncoding("UTF-8");
			cfg.setTemplateExceptionHandler(TemplateExceptionHandler.HTML_DEBUG_HANDLER);
			cfg.setIncompatibleImprovements(new Version(2, 3, 20));
			
			Template temp = cfg.getTemplate(template);
			File targetFile = new File(targetDir);
			if(!targetFile.exists()) {
				targetFile.mkdirs();
			}
			Writer out = new OutputStreamWriter(new FileOutputStream(new File(targetDir+result)));
			temp.process(data, out);  
		} catch (IOException e) {
			e.printStackTrace();
		} catch (TemplateException e) {
			e.printStackTrace();
		}
		
		
	}
	
	public static void generateModel(Map<String, List<Map<String, Object>>> map, String groupName, String projectName, String baseDir) {
		
		for(Entry<String, List<Map<String, Object>>> entry : map.entrySet()) {
			try {
				Map<String, Object> root = new HashMap<String, Object>();
				String pkgName = groupName+"."+projectName+".model";
				root.put("pkgName", pkgName);
				root.put("className", convertTableNameToClassName(entry.getKey()));
				
				Map<String, String> propMap = new HashMap<String, String>();
				List<Map<String,Object>> value = entry.getValue();
				for(Map<String, Object> m : value) {
					String dataType = m.get("DATA_TYPE").toString();
					propMap.put(convertColumnToProperty(m.get("COLUMN_NAME").toString()),DataTypeUtil.findJavaTypeByOracleType(dataType));
				}
				root.put("propMap", propMap);
				
				generate("model.ftl", root, convertTableNameToClassName(entry.getKey())+".java", baseDir + pkgName.replace(".", "\\")+"\\");
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	public static void generateVO(Map<String, List<Map<String, Object>>> map, String groupName, String projectName, String baseDir) {
		for(Entry<String, List<Map<String, Object>>> entry : map.entrySet()) {
			try {
				Map<String, Object> root = new HashMap<String, Object>();
				String pkgName = groupName+"."+projectName+".vo";
				root.put("pkgName", pkgName);
				root.put("className", convertTableNameToClassName(entry.getKey())+"VO");
				
				generate("VO.ftl", root, convertTableNameToClassName(entry.getKey())+"VO.java", baseDir+pkgName.replace(".", "\\")+"\\");
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	public static void generateMyBatisMapper(Map<String, List<Map<String, Object>>> map, String groupName, String projectName, String baseDir) {
		for(Entry<String, List<Map<String, Object>>> entry : map.entrySet()) {
			try {
				Map<String, Object> root = new HashMap<String, Object>();
				String pkgName = groupName+"."+projectName+".dao";
				root.put("pkgName", pkgName);
				root.put("className", convertTableNameToClassName(entry.getKey()));
				root.put("tableName", entry.getKey());
				
				List<DataRelation> propColTypeList = new ArrayList<DataRelation>();
				List<Map<String,Object>> value = entry.getValue();
				for(Map<String, Object> m : value) {
					if(m.get("COLUMN_NAME").toString().equalsIgnoreCase("ID")) {
						continue;
					}
					
					String dataType = m.get("DATA_TYPE").toString();
					propColTypeList.add(new DataRelation(m.get("COLUMN_NAME").toString(), 
							convertColumnToProperty(m.get("COLUMN_NAME").toString()),
							DataTypeUtil.findJdbcTypeBySqlType(dataType)));
				}
				root.put("propColTypeList", propColTypeList);
				
				generate("mybatisMapper.ftl", root, convertTableNameToClassName(entry.getKey())+"Mapper.xml", baseDir + "mybatis.sqlMap.base".replace(".", "\\")+"\\");
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	public static void generateDaoMapper(Map<String, List<Map<String, Object>>> map, String groupName, String projectName, String baseDir) {
		for(Entry<String, List<Map<String, Object>>> entry : map.entrySet()) {
			try {
				Map<String, Object> root = new HashMap<String, Object>();
				String pkgName = groupName+"."+projectName+".dao";
				root.put("pkgName", pkgName);
				root.put("className", convertTableNameToClassName(entry.getKey()));
				root.put("tableName", entry.getKey());
				
				generate("basedao.ftl", root, "Base"+convertTableNameToClassName(entry.getKey())+"Mapper.java", baseDir + pkgName.replace(".", "\\")+"\\");
				generate("dao.ftl", root, convertTableNameToClassName(entry.getKey())+"Mapper.java", baseDir + pkgName.replace(".", "\\")+"\\");
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	private static void generateMapperTestCase(Map<String, List<Map<String, Object>>> tableInfoCache, String groupName, String projectName, String baseDir) {
		
	}
	
	
}
